package com.etc.usercenter.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.etc.common.Code;
import com.etc.common.CodeMessage;
import com.etc.usercenter.domain.JwtUser;
import com.etc.usercenter.domain.LoginUser;
import com.etc.usercenter.utils.JwtTokenUtils;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 
 * Filename:    JWTAuthenticationFilter.java  
 * Description:   登陆用户密码验证过滤器，前置
 * Copyright:   Copyright (c) 2018-2019 All Rights Reserved.
 * Company:     chinasofti.com Inc.
 * @author:     mazheng 
 * @version:    1.0  
 * Create at:   2020年3月4日 下午3:37:42  
 *  
 * Modification History:  
 * Date         Author      Version     Description  
 * ------------------------------------------------------------------  
 * 2020年3月4日      mazheng      1.0         1.0 Version  
 *
 */
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private ThreadLocal<Integer> rememberMe = new ThreadLocal<>();
    private AuthenticationManager authenticationManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        super.setFilterProcessesUrl("/admin/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {

        // 从输入流中获取到登录的信息
        LoginUser loginUser = null;
        try {
            loginUser = new ObjectMapper().readValue(request.getInputStream(), LoginUser.class);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
//        LoginUser loginUser = new LoginUser(request.getParameter("username"),request.getParameter("password"), Integer.valueOf(request.getParameter("rememberMe")));
        rememberMe.set(loginUser.getRememberMe());
        return authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList<>())
        );
    }

    // 成功验证后调用的方法
    // 如果验证成功，就生成token并返回
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {

        JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
        System.out.println("jwtUser:" + jwtUser.toString());
        boolean isRemember = (rememberMe.get() == null ? 0 : 1 )== 1;

        String role = "";
        Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
        for (GrantedAuthority authority : authorities){
            role = authority.getAuthority();
        }

        String token = JwtTokenUtils.createToken(jwtUser.getUsername(), role, isRemember);
//        String token = JwtTokenUtils.createToken(jwtUser.getUsername(), false);
        // 返回创建成功的token
        // 但是这里创建的token只是单纯的token
        // 按照jwt的规定，最后请求的时候应该是 `Bearer token`
        response.setHeader("token", JwtTokenUtils.TOKEN_PREFIX + token);
        // cookie方式设置
        Cookie newVisitorCookie = new Cookie(JwtTokenUtils.TOKEN, JwtTokenUtils.TOKEN_PREFIX + token);
        newVisitorCookie.setMaxAge((int) (JwtTokenUtils.expiration/60));
        // 二级域名设置
//        newVisitorCookie.setDomain(".google.com");
        response.addCookie(newVisitorCookie);
        
        Map map = new HashMap();
        map.put("code", "1");
        map.put("token", JwtTokenUtils.TOKEN_PREFIX + token);
        map.put("username", jwtUser.getUsername());
        map.put("role", jwtUser.getAuthorities());
        ObjectMapper mapper = new ObjectMapper(); //转换器  
        //测试01：对象--json  
        String json=mapper.writeValueAsString(map); //将对象转换成json
        response.getWriter().write(json);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
//        response.getWriter().write("authentication failed, reason: " + failed.getMessage());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        if (failed instanceof BadCredentialsException) {
            response.getWriter().write(new ObjectMapper().writeValueAsString( CodeMessage.faild(Code.FAIL, "密码不正确")));
        } else if (failed instanceof InternalAuthenticationServiceException) {
            response.getWriter().write(new ObjectMapper().writeValueAsString( CodeMessage.faild(Code.FAIL, "用户不正确")));
        } else {
            response.getWriter().write(new ObjectMapper().writeValueAsString( CodeMessage.faild(Code.FAIL, failed.getMessage())));
        }
        
        
    }
}
